﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace LowLevelGraphics.Filter
{
    /// <summary>
    /// Filters multiples of a color.
    /// But what is a multiple?
    /// Let's define this by showing you each component value
    /// of a certain rgb color:
    /// 
    /// if we got for example
    /// color 1: 110, 220, 220
    /// 
    /// and we find another color which could be build out of color 1
    /// by multiplying each channel with the same factor
    /// this is a multiple.
    /// 
    /// So color 2 could be:
    /// color 2: 55, 110, 110
    /// </summary>
    public class FilterMultiples : BaseImageFilter
    {
        protected Color m_ColorReplace = Color.Transparent;

        //true = Remove only multiples of white
        //false = Remove rest
        protected bool m_bRemove = true;

        /// <summary>
        /// Default constructor
        /// </summary>
        public FilterMultiples()
        {
            m_ColorReplace = Color.Black;
        }

        /// <summary>
        /// Specify color to replace directly
        /// </summary>
        /// <param name="_colorReplace"></param>
        public FilterMultiples(Color _colorReplace)
        {
            m_ColorReplace = _colorReplace;
        }

        /// <summary>
        /// used to clone this instance
        /// </summary>
        /// <param name="_filterMultiples"></param>
        internal FilterMultiples(FilterMultiples _filterMultiples)
        {
            m_ColorReplace = _filterMultiples.m_ColorReplace;
            m_bRemove = _filterMultiples.m_bRemove;
        }

        /// <summary>
        /// Gets or sets the replacing color
        /// </summary>
        public Color ReplaceColor
        {
            get { return m_ColorReplace; }
            set { m_ColorReplace = value; }
        }

        /// <summary>
        /// Gets or sets if this color should be remove
        /// </summary>
        public bool Remove
        {
            get { return m_bRemove; }
            set { m_bRemove = value; }
        }

        /// <summary>
        /// Executes this filter
        /// </summary>
        /// <param name="_bitmap"></param>
        public override UnsafeBitmap Execute(UnsafeBitmap _bitmap)
        {
            FilterMultiplesOfWhite(_bitmap, m_ColorReplace);
            return _bitmap;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="bitmap"></param>
        private void FilterMultiplesOfWhite(UnsafeBitmap bitmap)
        {
            FilterMultiplesOfWhite(bitmap, Color.Black);
        }

        /// <summary>
        /// This is the real filter routine
        /// </summary>
        /// <param name="_bitmap"></param>
        /// <param name="_colorReplace"></param>
        private void FilterMultiplesOfWhite(UnsafeBitmap _bitmap, Color _colorReplace)
        {
            UnsafeBitmap bitmap = _bitmap;

            Color color = Color.FromArgb(255, 255, 255);

            bool bFound = false;

            bool b = false;

            int nHeight = _bitmap.Height;
            int nWidth = _bitmap.Width;

            int y = 0;
            int x = 0;
            for (y = 0; y < nHeight; y++)
            {
                for (x = 0; x < nWidth - 1; x++)
                {
                    bFound = false;
                    if (ColorFunctions.IsMultipleOfGray(color, _bitmap.GetPixel(x, y), 0))
                    {
                        bFound = true;
                    }
                    b = bFound;
                    if (m_bRemove) b = !bFound;
                    if (b) 
                    {
                        _bitmap.SetPixel(x, y, _colorReplace);
                    }
                }
            }
        }

        /// <summary>
        /// Use this to create a deep copy
        /// </summary>
        /// <returns></returns>
        public override object Clone()
        {
            return new FilterMultiples(this);
        }
    }
}
